﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ct = Constant;

public class ZllFirst{
    //第k种连子数会有五个对应的[i,j,k]
    private bool[,,] PAllPossibleLinks = new bool[Constant.CrossCount, Constant.CrossCount, Constant.AllPossible_15];
    private bool[,,] ZllAllPossibleLinks = new bool[Constant.CrossCount, Constant.CrossCount, Constant.AllPossible_15];
    private Dictionary<int, Point[]> LinkIdx2ChessList = new Dictionary<int, Point[]>();
    private Dictionary<Point, int[]> Point2PossibleLinkIdx = new Dictionary<Point, int[]>();

    //表示第i种可能性的连子数的棋子数
    private int[] PlayerLinksChessNum = new int[Constant.AllPossible_15];
    private int[] ZllLinksChessNum = new int[Constant.AllPossible_15];

    private int[,] PlayerCrossScores = new int[Constant.CrossCount, Constant.CrossCount];
    private int[,] ZllCrossScores = new int[Constant.CrossCount, Constant.CrossCount];

    public ZllFirst()
    {
        ResetData();
    }

    public Point Execute(CrossVal[,] boardData, Point chessPos)
    {
        ResetData();
        CalLinksChessNum(boardData);
        CalCrossScore(boardData);
        return GetDownCross(boardData);
    }

    Point GetDownCross(CrossVal[,] boardData)
    {
        Point PlayerPt = new Point();
        Point ZllPt = new Point();
        int PMaxScore = -1;
        int ZllMaxScore = -1;
        for (int i = 0; i < Constant.CrossCount; i++)
        {
            for (int j = 0; j < Constant.CrossCount; j++)
            {
                if (boardData[i, j] != CrossVal.nil)
                    continue;
                if(PlayerCrossScores[i,j] > PMaxScore)
                {
                    PMaxScore = PlayerCrossScores[i, j];
                    PlayerPt.x = i;
                    PlayerPt.y = j;
                }

                if (ZllCrossScores[i, j] > ZllMaxScore)
                {
                    ZllMaxScore = ZllCrossScores[i, j];
                    ZllPt.x = i;
                    ZllPt.y = j;
                }
            }
        }
        return (PMaxScore > ZllMaxScore) ? PlayerPt : ZllPt;
    }

    void CalCrossScore(CrossVal[,] boardData)
    {
        for (int i = 0; i < Constant.CrossCount; i++)
        {
            for (int j = 0; j < Constant.CrossCount; j++)
            {
                if(boardData[i,j] == CrossVal.nil)
                {
                    ZllCrossScores[i, j] = 0;
                    PlayerCrossScores[i, j] = 0;
                    for (int idx =0; idx < ct.AllPossible_15; idx++)
                    {
                        if(PAllPossibleLinks[i,j,idx])
                            switch(PlayerLinksChessNum[idx])
                            {
                                case 1:
                                    PlayerCrossScores[i, j] += ct.PlayerScore_1;
                                    break;
                                case 2:
                                    PlayerCrossScores[i, j] += ct.PlayerScore_2;
                                    break;
                                case 3:
                                    PlayerCrossScores[i, j] += ct.PlayerScore_3;
                                    break;
                                case 4:
                                    PlayerCrossScores[i, j] += ct.PlayerScore_4;
                                    break;
                            }
                        if(ZllAllPossibleLinks[i,j,idx])
                            switch (ZllLinksChessNum[idx])
                            {
                                case 1:
                                    ZllCrossScores[i, j] += ct.ZLLScore_1;
                                    break;
                                case 2:
                                    ZllCrossScores[i, j] += ct.ZLLScore_2;
                                    break;
                                case 3:
                                    ZllCrossScores[i, j] += ct.ZLLScore_3;
                                    break;
                                case 4:
                                    ZllCrossScores[i, j] += ct.ZLLScore_4;
                                    break;
                            }
                    }
                }
            }
        }
    }

    void CalLinksChessNum(CrossVal[,] boardData)
    {
        for(int i=0; i<Constant.CrossCount; i++)
        {
            for(int j=0; j<Constant.CrossCount; j++)
            {
                CrossVal chess = boardData[i, j];
                if (chess == CrossVal.nil)
                    continue;
                bool isAIChess = (chess == Datacenter.playerManager.GetPlayerValue(Player.AI_1));
                for (int z = 0; z < Constant.AllPossible_15; z++)
                {
                    if (isAIChess)
                    {
                        if(ZllAllPossibleLinks[i,j,z] && ZllLinksChessNum[z] != -1)
                            ZllLinksChessNum[z]++;

                        if(PAllPossibleLinks[i, j, z])
                        { 
                            PAllPossibleLinks[i, j, z] = false;
                            PlayerLinksChessNum[z] = -1;
                        }
                    }
                    else
                    {
                        if (PAllPossibleLinks[i, j, z] && PlayerLinksChessNum[z] != -1)
                            PlayerLinksChessNum[z]++;

                        if (ZllAllPossibleLinks[i, j, z])
                        {
                            ZllAllPossibleLinks[i, j, z] = false;
                            ZllLinksChessNum[z] = -1;
                        }
                    }
                }
            }
        }
    }

    int InitDirectionLinks(Point direction, int MaxI, int MaxJ, int possibleIndex, int MinI = 0, int MinJ = 0)
    {
        for (int i = MinI; i < MaxI; i++)
        {
            for (int j = MinJ; j < MaxJ; j++)
            {
                Point point = new Point(i, j);
                Point[] chessList = new Point[Constant.GobangNum];
                for (int k = 0; k < Constant.GobangNum; k++)
                {
                    PAllPossibleLinks[i+k*direction.x, j+k*direction.y, possibleIndex] = true;
                    ZllAllPossibleLinks[i + k * direction.x, j + k * direction.y, possibleIndex] = true;
                    Point pt = new Point(i + k * direction.x, j + k * direction.y);
                    chessList[k] = pt;
                }
                LinkIdx2ChessList.Add(possibleIndex, chessList);
                possibleIndex++;
            }
        }
        return possibleIndex;
    }

    void InitAllPossibleLinks()
    {
        int possibleIndex = 0;
        LinkIdx2ChessList.Clear();
        possibleIndex = InitDirectionLinks(new Point(1, 0), ct.CrossCount - 4, ct.CrossCount, possibleIndex);
        possibleIndex = InitDirectionLinks(new Point(0, 1), ct.CrossCount,     ct.CrossCount - 4, possibleIndex);
        possibleIndex = InitDirectionLinks(new Point(1, 1), ct.CrossCount - 4, ct.CrossCount - 4, possibleIndex);
        InitDirectionLinks(new Point(1, -1), ct.CrossCount - 4, ct.CrossCount, possibleIndex, 0, 4);
    }

    void ResetData()
    {
        InitAllPossibleLinks();

        for (int i=0; i<Constant.AllPossible_15; i++)
        {
            PlayerLinksChessNum[i] = 0;
            ZllLinksChessNum[i] = 0;
        }

        for(int i=0; i<Constant.CrossCount; i++)
        {
            for(int j=0; j<Constant.CrossCount; j++)
            {
                PlayerCrossScores[i, j] = 0;
                ZllCrossScores[i, j] = 0;
            }
        }
    }
}
